#include "ui/attack/AttackerInfo.h"
#include "gui/GuiFactory.h"
#include "gui/Panel3Sprite.h"
#include "scene/SceneController.h"
#include "location/GameLocationController.h"
#include "settings/GameEventManager.h"
#include "utils/StringUtils.h"
#include "utils/ScreenUtils.h"
#include "parameters/data/ParametersCollection.h"
#include "attack/entities/CharacterBattleData.h"
#include "localization/Localization.h"
#include "location/LocationEventsDispatcher.h"

const float AttackerInfo::ORIGINAL_SIZE_ICON_GOLD_X = 98.0f;
const float AttackerInfo::ORIGINAL_SIZE_ICON_GOLD_Y = 96.0f;
const float AttackerInfo::ORIGINAL_SIZE_ICON_OIL_X = 81.0f;
const float AttackerInfo::ORIGINAL_SIZE_ICON_OIL_Y = 98.0f;
const float AttackerInfo::ORIGINAL_SIZE_ICON_DIAMOND_X = 97.0f;
const float AttackerInfo::ORIGINAL_SIZE_ICON_DIAMOND_Y = 93.0f;
const float AttackerInfo::ORIGINAL_SIZE_ICON_TROOPS_X = 106.0f;
const float AttackerInfo::ORIGINAL_SIZE_ICON_TROOPS_Y = 120.0f;


AttackerInfo::AttackerInfo() :
moneyOilLabel(NULL),
moneyGoldLabel(NULL),

progressGold(NULL),
progressOil(NULL),

maxGoldLabel(NULL),
maxOilLabel(NULL) {
}

AttackerInfo::~AttackerInfo() {
	LocationEventsDispatcher::getInstance()->getStarAchievedSignal().removeListener(this, &AttackerInfo::onStarAchieved);
}

AttackerInfo* AttackerInfo::create() {
	AttackerInfo* result = new AttackerInfo();
	if (result && result->init()) {
		result->autorelease();
		return result;
	}
	CC_SAFE_DELETE(result);
	return NULL;
}

bool AttackerInfo::init() {

	/************************
	Правый верхний угол главного ГУИ. Счет пользователя.
	- золото
	- нефть
	- алмазы
	************************/

	const CCSize& size = ScreenUtils::getSize();
	const float scale = ScreenUtils::getScale();
	const float elementsBaseScale = scale / 1.4f;

	float yPos = size.height;

	//const float progressScale = elementsBaseScale;

	const float sideOffset = 30 * elementsBaseScale;

	const float progressWidth = 447.0f * elementsBaseScale;
	const float progressHeight = 66.0f * elementsBaseScale;


	const ccColor3B fontColor = ccc3(254, 244, 240);

	/* Блок золота */
	{
		yPos -= 44 * elementsBaseScale;

		// Текст макс. кол-ва золота
		maxGoldLabel = TextLabel::create(
			"",
			30 * scale,
			fontColor,
			CCSize::ZERO,
			LabelTextStyle::SHADOW
			);
		maxGoldLabel->setAlignment(kCCTextAlignmentLeft);
		maxGoldLabel->setPosition(sideOffset + 90 * elementsBaseScale, yPos);
		addChild(maxGoldLabel);

		// Прогресс
		progressGold = MainUIProgressBar::create(progressWidth, progressHeight, PROGRESS_BAR_GOLD, PROGRESS_BAR_NORMAL);
		progressGold->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_LEFT);
		progressGold->setPosition(sideOffset, yPos - progressHeight);
		addChild(progressGold);

		yPos -= progressHeight;

		// Иконка
		CCSprite * goldImage = GuiFactory::createSprite(CurrencyEntity::GOLD->getIcon());
		goldImage->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_LEFT);
		goldImage->setScaleX(elementsBaseScale * ORIGINAL_SIZE_ICON_GOLD_X / goldImage->getContentSize().width);
		goldImage->setScaleY(elementsBaseScale * ORIGINAL_SIZE_ICON_GOLD_Y / goldImage->getContentSize().height);
		goldImage->setPosition(CCPoint(
			progressGold->getPositionX() - 13 * elementsBaseScale,
			progressGold->getPositionY() + 14 * elementsBaseScale));
		addChild(goldImage);

		// Кол-во денег
		moneyGoldLabel = TextLabel::create(
			"",
			46 * scale,
			fontColor,
			progressGold->getContentSize(),
			LabelTextStyle::SHADOW
			);
		moneyGoldLabel->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_LEFT);
		moneyGoldLabel->setPosition(progressGold->getPosition());
		addChild(moneyGoldLabel);
	}

	/* Блок нефти */
	{
		yPos -= 53 * elementsBaseScale;

		// Текст макс. кол-ва
		maxOilLabel = TextLabel::create(
			"",
			30 * scale,
			fontColor,
			CCSize::ZERO,
			LabelTextStyle::SHADOW
			);
		maxOilLabel->setAlignment(kCCTextAlignmentLeft);
		maxOilLabel->setPosition(sideOffset + 90 * elementsBaseScale, yPos);
		addChild(maxOilLabel);

		// Прогресс
		progressOil = MainUIProgressBar::create(progressWidth, progressHeight, PROGRESS_BAR_OIL, PROGRESS_BAR_NORMAL);
		progressOil->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_LEFT);
		progressOil->setPosition(sideOffset, yPos - progressHeight);
		addChild(progressOil);

		yPos -= progressHeight;

		// Иконка
		CCSprite * oilImage = GuiFactory::createSprite(CurrencyEntity::OIL->getIcon());
		oilImage->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_LEFT);
		oilImage->setScaleX(elementsBaseScale * ORIGINAL_SIZE_ICON_OIL_X / oilImage->getContentSize().width);
		oilImage->setScaleY(elementsBaseScale * ORIGINAL_SIZE_ICON_OIL_Y / oilImage->getContentSize().height);
		oilImage->setPosition(CCPoint(
			progressOil->getPositionX() - 11 * elementsBaseScale,
			progressOil->getPositionY() + 14 * elementsBaseScale));
		addChild(oilImage);

		// Кол-во нефти
		moneyOilLabel = TextLabel::create(
			"",
			46 * scale,
			fontColor,
			progressOil->getContentSize(),
			LabelTextStyle::SHADOW
			);
		moneyOilLabel->setPosition(progressOil->getPosition());
		addChild(moneyOilLabel);
	}

	yPos = createCurrencyProgressBars(yPos);

	/* Блок количества сил в запасе (невысаженных юнитов) */
	{
		yPos -= 53 * elementsBaseScale;

		// Прогресс
		MainUIProgressBar * progressCapacity = MainUIProgressBar::create(390 * elementsBaseScale, progressHeight, PROGRESS_BAR_ORANGE, PROGRESS_BAR_NORMAL);
		progressCapacity->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_LEFT);
		progressCapacity->setPosition(sideOffset, yPos - progressHeight);
		progressCapacity->setProgress(0);
		addChild(progressCapacity);

		// Текст
		troopsLabel = TextLabel::create(
			Localization::tr("LID Army:"),
			42 * elementsBaseScale,
			fontColor,
			CCSize(progressCapacity->getContentSize().width, 0),
			LabelTextStyle::SHADOW
			);
		troopsLabel->setPosition(sideOffset, yPos);
		addChild(troopsLabel);

		yPos -= progressHeight;

		// Иконка
		CCSprite * troopsIcon = GuiFactory::createSprite("gui/main_ui/icon_army.png");
		troopsIcon->setScaleX(elementsBaseScale * ORIGINAL_SIZE_ICON_TROOPS_X / troopsIcon->getContentSize().width);
		troopsIcon->setScaleY(elementsBaseScale * ORIGINAL_SIZE_ICON_TROOPS_X / troopsIcon->getContentSize().height);
		troopsIcon->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_LEFT);
		troopsIcon->setPosition(CCPoint(progressCapacity->getPositionX() - 11 * elementsBaseScale, progressCapacity->getPositionY()));
		addChild(troopsIcon);
		const float iconWidth = troopsIcon->getContentSize().width * troopsIcon->getScaleX();

		// Кол-во
		troopsLabel = TextLabel::create(
			"",
			46 * scale,
			fontColor,
			CCSize(progressCapacity->getContentSize().width - 0.8f*iconWidth, progressCapacity->getContentSize().height),
			LabelTextStyle::SHADOW
			);
		troopsLabel->setPositionX(progressCapacity->getPositionX() + 0.8f*iconWidth);
		troopsLabel->setPositionY(progressCapacity->getPositionY());
		addChild(troopsLabel);
	}

	LocationEventsDispatcher::getInstance()->getStarAchievedSignal().addListener(this, &AttackerInfo::onStarAchieved);

	return true;
}

void AttackerInfo::onStarAchieved(int starCount) {
	showEffectMoney(starCount);
}

float AttackerInfo::createCurrencyProgressBars(float yPos) {

	const float elementsBaseScale = ScreenUtils::getScale() / 1.4f;
	const std::list<const CurrencyEntity *> & currencies = CurrencyEntity::getAllAvailableCurrency();
	for (const CurrencyEntity * currencyEntity : currencies) {
		if (!GameEventManager::getInstance()->isCurrencyEnabled(currencyEntity)) {
			continue;
		}

		if (currencies.size() > 1 && currencyEntity == CurrencyEntity::DIAMOND)
			continue;

		if (currencyEntity == CurrencyEntity::OIL || currencyEntity == CurrencyEntity::GOLD) {
			continue;
		}

		// Тупо в ПвЕ не показываем тыквы, так как их нельзя там заработать
		if (SceneController::getCurrentLocationController()->getLocationType() == LocationTypeEnum::PVE && GameEventManager::getInstance()->isEventCurrency(currencyEntity)) {
			continue;
		}

		yPos -= 44 * elementsBaseScale;

		// Рамка для кол-ва
		Panel3Sprite * currencyBarBg = Panel3Sprite::create(390 * elementsBaseScale, 75 * elementsBaseScale,
			"gui/main_ui_progressbar/progress_left.png",
			"gui/main_ui_progressbar/progress_center.png",
			"gui/main_ui_progressbar/progress_right.png");
		currencyBarBg->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_RIGHT);
		currencyBarBg->setScaleX(-1 * currencyBarBg->getScaleX());
		currencyBarBg->setPosition(CCPoint(30 * elementsBaseScale, yPos - currencyBarBg->getContentSize().height));
		addChild(currencyBarBg);

		Panel3Sprite * additionalBar = Panel3Sprite::create(390 * elementsBaseScale, 75 * elementsBaseScale,
			"gui/main_ui_progressbar/light_progress_small_left.png",
			"gui/main_ui_progressbar/light_progress_small_center.png",
			"gui/main_ui_progressbar/light_progress_small_right.png");
		additionalBar->setAnchorPoint(CCPoint::ANCHOR_BOTTOM_RIGHT);
		additionalBar->setScaleX(-1 * additionalBar->getScaleX());
		additionalBar->setPosition(currencyBarBg->getPosition());
		addChild(additionalBar);

		yPos -= currencyBarBg->getContentSize().height;

		// Иконка
		CCSprite * currencyImage = GuiFactory::createSprite(currencyEntity->getIcon());
		currencyImage->setAnchorPoint(CCPoint::ANCHOR_MIDDLE);
		currencyImage->setScale(elementsBaseScale * ORIGINAL_SIZE_ICON_DIAMOND_Y / currencyImage->getContentSize().height);
		currencyImage->setPositionX(currencyBarBg->getPositionX() - 8 * elementsBaseScale + currencyImage->getContentSize().width*currencyImage->getScaleX() / 2);
		currencyImage->setPositionY(currencyBarBg->getPositionY() + 12 * elementsBaseScale + currencyImage->getContentSize().height*currencyImage->getScaleY() / 2);
		addChild(currencyImage);

		// Кол-во
		TextLabel * moneyLabel = TextLabel::create(
			StringUtils::formatInt(CharacterBattleData::getInstance()->getMoney(currencyEntity)),
			BBGuiConst::getLargeFontSize(),
			BBGuiConst::TEXT_COLOR_LIGHT,
			currencyBarBg->getContentSize(),
			LabelTextStyle::SHADOW
			);
		moneyLabel->setPosition(currencyBarBg->getPosition());
		addChild(moneyLabel);

		mapCurrencyToTextLabel.insert(std::make_pair( currencyEntity, moneyLabel ));
		mapCurrencyToIcon.insert(std::make_pair( currencyEntity, currencyImage ));
	}
	return yPos;
}


void AttackerInfo::update() {

	ParametersCollection & parameterCollection = CharacterBattleData::getInstance()->getParameters();

	const ParameterValue& gold = parameterCollection.getParameter(ParameterEntity::CAPACITY_GOLD);
	moneyGoldLabel->setString(StringUtils::formatInt(gold.current).c_str());
	progressGold->setProgress(100.f * (float)gold.current / (float)gold.base);
	maxGoldLabel->setString(Localization::tr("LID Max: %s", StringUtils::formatInt(gold.base)));

	const ParameterValue& oil = parameterCollection.getParameter(ParameterEntity::CAPACITY_OIL);
	moneyOilLabel->setString(StringUtils::formatInt(oil.current).c_str());
	progressOil->setProgress(100.f * (float)oil.current / (float)oil.base);
	maxOilLabel->setString(Localization::tr("LID Max: %s", StringUtils::formatInt(oil.base)));

	const int maxTroops = CharacterBattleData::getInstance()->getMaxCapacity();
	const int troops = CharacterBattleData::getInstance()->getCurrentCapacity();

	troopsLabel->setString(StringUtils::format("%i/%i", troops, maxTroops).c_str());
}

void AttackerInfo::showEffectMoney(int starCount) {
	LOG("AttackerInfo::showEffectMoney %i", starCount);

	for (const CurrencyEntity * currency : CurrencyEntity::getAllAvailableCurrency()) {
		if (!GameEventManager::getInstance()->isCurrencyEnabled(currency)) {
			continue;
		}

		if (currency == CurrencyEntity::DIAMOND)
			continue;

		// Тут перечисляем условия, при которых начисляем валюту
		if (GameEventManager::getInstance()->isEventCurrency(currency)) {

			std::map<const CurrencyEntity *, CCNode *>::iterator iter = mapCurrencyToIcon.find(currency);
			if (iter != mapCurrencyToIcon.end()) {

				int rewardSum = GameEventManager::getInstance()->getAttackReward(starCount);
				if (rewardSum <= 0) {
					continue;
				}

				CCPoint positionFrom = convertToNodeSpace(ScreenUtils::getScreenCenterPoint()) + CCPoint(0, 100 * ScreenUtils::getScale());

				CCSprite * star = GuiFactory::createSprite(iter->first->getIcon());
				star->setAnchorPoint(CCPoint::ANCHOR_MIDDLE);
				star->setScale(0);
				star->setPosition(positionFrom);
				addChild(star, 1);

				// Первая фаза, тупо показываем бонус
				CCScaleTo * scaleTo1 = CCScaleTo::create(0.1f, 2.5f*iter->second->getScale());
				CCDelayTime * delayTime = CCDelayTime::create(0.05f);
				CCSequence * phase1 = CCSequence::createWithTwoActions(scaleTo1, delayTime);

				// Вторая фаза, уносим и скейлим его
				ccBezierConfig config;
				config.endPosition = iter->second->getPosition();
				config.controlPoint_1 = CCPoint(positionFrom.x, 1.2f * positionFrom.y);
				config.controlPoint_2 = iter->second->getPosition();
				CCBezierTo * bezierTo = CCBezierTo::create(0.8f, config);

				CCScaleTo * scaleTo2 = CCScaleTo::create(0.8f, iter->second->getScale());
				CCSpawn * phase2 = CCSpawn::createWithTwoActions(bezierTo, scaleTo2);
				CCEaseInOut * moddedPhase2 = CCEaseInOut::create(phase2, 3.3f);

				// В конце удаляем
				CCCallFunc * removeEffectFunc = CCCallFuncND::create(this, callfuncND_selector(AttackerInfo::removeEffect), (void*)new Price(currency, rewardSum));

				CCDelayTime * delayTimeForStars = CCDelayTime::create(0.4f);
				CCSequence * resultAction = CCSequence::create(delayTimeForStars, phase1, moddedPhase2, removeEffectFunc, NULL);
				star->runAction(resultAction);
			}
		}
	}
}

void AttackerInfo::removeEffect(CCNode * effect, void * data) {
	const Price * price = static_cast<const Price *>(data);
	LOG("AttackerInfo::removeEffect %i", price->getSum());
	CharacterBattleData::getInstance()->deltaPrice(*price);
	int money = CharacterBattleData::getInstance()->getMoney(price->getCurrency());
	if (effect)
		effect->removeFromParent();
	std::map<const CurrencyEntity *, TextLabel *>::iterator iter = mapCurrencyToTextLabel.find(price->getCurrency());
	if (iter != mapCurrencyToTextLabel.end()) {
		iter->second->setString(StringUtils::formatInt(money));
	}
	delete price;
}

void AttackerInfo::updateCurrency(const CurrencyEntity* currency) {
	std::map<const CurrencyEntity *, TextLabel *>::iterator iter = mapCurrencyToTextLabel.find(currency);
	if (iter != mapCurrencyToTextLabel.end()) {
		int money = CharacterBattleData::getInstance()->getMoney(currency);
		iter->second->setString(StringUtils::formatInt(money));
	}
}
